/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package TabuSearch;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.biojava.bio.structure.*;
import rotlib.RotamerLibrary;
import rotlib.RotamerLibraryCollection;
import utils.*;

/**
 *
 * @author Valkyrie
 */
public class AllRotamerInteractions {
//    public static ArrayList<ArrayList<ArrayList<ArrayList<Double>>>> allInteractions;

    public static HashMap<Integer, HashMap<Integer, HashMap<Integer, HashMap<Integer, Double>>>> allInteractions;
    public static HashMap<Integer, HashMap<Integer,Double>> allSCBBInteractions;
    public static Structure s;
    public static RotamerLibraryCollection rlc;
    public static AminoacidsGrid aGrid;
    public static HashMap<Integer, AminoacidExtended> aminoacidMap;
    public static HashMap<Integer,ArrayList<Integer>> enabledRotamers;
    public static double interval = 6;
    public static double Energy;
    public static double totalSelfEnergy;
    public static HashMap<Integer,Double> selfEnergies;
    public static Solution sol;
    public static HashMap<Integer,ArrayList<Integer>> AAsToVerify;
    public static HashMap<Integer,Integer> Rotamers;
    public static HashMap<Integer,Integer> oldRotamers;
    public static HashMap<Integer,Double> AAInteractions;
    public static HashMap<Integer,Double> CRatios;
    public static double totalvdw,totalcratio,c;
    public static HashMap<String,Double> wellDepths = new HashMap<>();

    public AllRotamerInteractions(Structure s, RotamerLibraryCollection rlc, AminoacidsGrid aGrid, Solution sol) {
        totalvdw=totalcratio=c=0;
        AllRotamerInteractions.s = s;
        AllRotamerInteractions.Energy=0;
        AllRotamerInteractions.totalSelfEnergy=0;
        AllRotamerInteractions.selfEnergies=new HashMap<>();
        AllRotamerInteractions.AAsToVerify = new HashMap<>();
        AllRotamerInteractions.Rotamers= initRotamers(sol);
        AllRotamerInteractions.oldRotamers=initRotamers(sol);
        AllRotamerInteractions.CRatios=new HashMap<>();
        AllRotamerInteractions.sol=sol;
        AllRotamerInteractions.aGrid = aGrid;
        AllRotamerInteractions.rlc = rlc;
        AllRotamerInteractions.aminoacidMap = aGrid.aminoacidMap;
        initWellDepths();
        enabledRotamers = new HashMap<>();
        allInteractions = new HashMap<>();
        allSCBBInteractions = new HashMap<>();
        calculateAllRotamerInteractions();
        AllRotamerInteractions.AAInteractions=initAAInteractions();
    }

    public final void calculateAllRotamerInteractions() {
        int nResidues = TabuSearch.getSeqResLength(s);
        ArrayList<String> PDBsToVerify = new ArrayList<>();
        ArrayList<Integer> nearAAs=new ArrayList<>();
        AminoAcid aa1, aa2;
        int chain = 0, j = 0;
        RotamerLibrary rl, rl2;
        double energy = 0;
        double eSCBB=0;
        int i=0;


        try {
            Object[] keys=sol.getRomaterVector().get(0).keySet().toArray(new Integer[0]);//aGrid.aminoacidMap.keySet().toArray(new Integer[0]);
            Arrays.sort(keys);
            for (int key = 0; key < keys.length; key++) {
                i=Integer.parseInt(keys[key].toString()) ;
                aa1 = aGrid.getAminoacid(i);//(AminoAcid) s.getChain(chain).getAtomGroup(i);
                

                if (!aa1.getPDBName().equalsIgnoreCase("ALA") && !aa1.getPDBName().equals("GLY")) {

                    rl = rlc.getRotamerLibrary(aa1.getPDBName());
                    allInteractions.put(i, new HashMap<Integer, HashMap<Integer, HashMap<Integer, Double>>>());
                    allSCBBInteractions.put(i, new HashMap<Integer,Double>());

                    for (int r = 0; r < rl.getRotamer().size(); r++) {
                        if(rl.getRotamer().get(r).getProbabilityValue() < 1) {
                                continue;
                        }
                        aa1 = StructureUtil.createAminoacid(aa1, rl.getRotamer().get(r));
                        PDBsToVerify = aGrid.obtainAminoacidsToVerifyInCellAndNeighborhood(aminoacidMap.get(Integer.parseInt(aa1.getPDBCode())), interval);
                        allInteractions.get(i).put(r, new HashMap<Integer, HashMap<Integer, Double>>());
                        

                        for (int k = 0; k < PDBsToVerify.size(); k++) {
                            j = Integer.parseInt(PDBsToVerify.get(k))-1;
                            if(!nearAAs.contains(j))
                                    nearAAs.add(j);
                            
                            aa2 = aGrid.getAminoacid(j);
                            eSCBB += energySCBBSCWRL4(aa1,aa2);
                            
                            if(i<j){
                                
                                if (!aa2.getPDBName().equalsIgnoreCase("ALA") && !aa2.getPDBName().equals("GLY")) {

                                    rl2 = rlc.getRotamerLibrary(aa2.getPDBName());
                                    allInteractions.get(i).get(r).put(j, new HashMap<Integer, Double>());

                                    for (int s1 = 0; s1 < rl2.getRotamer().size(); s1++) {
                                        if(rl2.getRotamer().get(s1).getProbabilityValue() < 1) {
                                                continue;
                                        }
                                        aa2 = StructureUtil.createAminoacid(aa2, rl2.getRotamer().get(s1));
                                        if(i==33 && r==4 && j==96 && s1==29){
                                            energy = detailedEnergyBetweenSCSCWRL4(aa1, aa2);
                                        }
                                        else{
                                            energy = calculateEnergyBetweenSCSCWRL4(aa1, aa2);
                                        }
//                                        if(i==59 && r==2 && j==3 && s1==2){
//                                            for(Atom atx:aa2.getAtoms()){
//                                                System.out.println(atx.getX()+", "+atx.getY()+", "+atx.getZ());
//                                            }
//                                            System.out.println("->"+energy+" de "+aa1.getPDBName()+" y "+aa2.getPDBName());
//                                        }
//                                        if(i==3 && r==2 && j==59 && s1==2){
//                                            for(Atom atx:aa1.getAtoms()){
//                                                System.out.println(atx.getX()+", "+atx.getY()+", "+atx.getZ());
//                                            }
//                                            System.out.println("<-"+energy+" de "+aa1.getPDBName()+" y "+aa2.getPDBName());
//                                        }
                                        allInteractions.get(i).get(r).get(j).put(s1, energy);
                                    }
                                }
                            }
                        }
                        allSCBBInteractions.get(i).put(r, eSCBB);
                        eSCBB=0;
                    }
                }else{
                    //poner 0 para ala y gly en SCBB // ??????
                }
                if(nearAAs.contains(i))
                    nearAAs.remove(nearAAs.indexOf(i));
                AAsToVerify.put(i, nearAAs);
                nearAAs=new ArrayList<>();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    public void calculateSelfEnergies(){
        String name;
        int rot;
        AminoAcid a;
        double sum=0;
        Object[] keys=sol.getRomaterVector().get(0).keySet().toArray();
        Arrays.sort(keys);
        int aa=0;
            
        for(int i=0;i<aGrid.aminoacidMap.size();i++){
            a=(AminoAcid) s.getChain(0).getAtomGroup(i);
            name=a.getPDBName();
            aa=Integer.parseInt(keys[i].toString());
            rot=Integer.parseInt(sol.getRomaterVector().get(0).get(aa));
            selfEnergies.put(aa, aGrid.getRotamerFrequencyRASP(name,rot));
            sum+=selfEnergies.get(aa);
        }
        totalSelfEnergy=sum;
//        System.out.println("suma de auto-energias: "+sum);
    }

    public double minGminusH(AminoAcid g, AminoAcid h, AminoAcid f, RotamerLibrary rl) {
        int rotamers = rl.getRotamer().size();
        double energyG, energyH, residue, min_residue = Double.MAX_VALUE;


        for (int i = 0; i < rotamers; i++) {
            f = StructureUtil.createAminoacid(f, rl.getRotamer().get(i));
            energyG = calculateEnergyBetweenSC(g, f);
            energyH = calculateEnergyBetweenSC(h, f);
            residue = energyG - energyH;
            if (residue < min_residue) {
                min_residue = residue;
            }
        }

        return min_residue;
    }
    
    public double minGminusH(int i, int g, int h, int j) {
        RotamerLibrary rl= rlc.getRotamerLibrary(aGrid.getAminoacid(j).getPDBName());
        int rotamers = rl.getRotamer().size();
        double energyG, energyH, residue, min_residue = Double.MAX_VALUE;


        for (int s1 = 0; s1 < rotamers; s1++) {
            energyG = getInteraction(i,g,j,s1);
            energyH = getInteraction(i,h,j,s1);
            residue = energyG - energyH;
            if (residue < min_residue) {
                min_residue = residue;
            }
        }
//        if(min_residue!=0)
//            System.out.println("Diferente de cero!!");
//        System.out.println("min energy: "+min_residue);
        return min_residue;
    }
    //<editor-fold defaultstate="collapsed" desc="Calcular energía SC-BB">
    public static double energySCBB(AminoAcid aa1, AminoAcid aa2){
        double energy=0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1,aminoAcidIndex2 = -1;
        String[] atomList1,atomList2;
        double distance, MIN_DISTANCE, krep = 5.882, katt = 0.08;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa1.getPDBName());
        atomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa2.getPDBName());
        atomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        
        for (int i = 0; i < atomList1.length; i++) {
            if (aa1 != null && aa1.hasAtom(atomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < atomList2.length; j++) {
                    if (aa2 != null && aa2.hasAtom(atomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(atomList1[i]) && !StructureUtil.isSideChainAtom(atomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = aa1.getAtom(atomList1[i]);
                                atom2 = aa2.getAtom(atomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                
                                MIN_DISTANCE = StructureUtil.radius(aa1, atom1) + StructureUtil.radius(aa2, atom2);
                                possibleCollision++;
                                //                                if(distance <=(MIN_DISTANCE*0.6))
                                //                                    collisionCounter++;
                                if (distance <= MIN_DISTANCE) {
                                    energy += krep * (1 - (distance / MIN_DISTANCE));
                                    collisionCounter++;
                                } else if ((distance > MIN_DISTANCE) && (distance < (2 * MIN_DISTANCE))) {
                                    energy += katt * (Math.pow(distance / MIN_DISTANCE, 2) - 3 * (distance / MIN_DISTANCE) + 2);
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        //        return (collisionCounter/possibleCollision);
        return ((collisionCounter/possibleCollision)*19.4861137)+(energy);
        //        return energy;
    }
    
    public static double energySCBBRASP(AminoAcid aa1, AminoAcid aa2){
        double energy=0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1,aminoAcidIndex2 = -1;;
        String[] atomList1,atomList2;
        double distance, MIN_DISTANCE, krep = 5.882, katt = 0.08;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa1.getPDBName());
        atomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa2.getPDBName());
        atomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        double eij,dprima;
        
        for (int i = 0; i < atomList1.length; i++) {
            if (aa1 != null && aa1.hasAtom(atomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < atomList2.length; j++) {
                    if (aa2 != null && aa2.hasAtom(atomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(atomList1[i]) && !StructureUtil.isSideChainAtom(atomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = aa1.getAtom(atomList1[i]);
                                atom2 = aa2.getAtom(atomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                eij=wellDepths.get(atom1.getName().substring(0, 1) +"-"+atom2.getName().substring(0,1));
                                
                                MIN_DISTANCE = StructureUtil.radius(aa1, atom1) + StructureUtil.radius(aa2, atom2);
                                dprima=distance/MIN_DISTANCE;
                                possibleCollision++;
                                if(dprima<0.465){
                                    energy += (50*eij);
                                    //                                    System.out.println("1 slot: "+(50*eij));
                                    collisionCounter++;
                                }
                                else{
                                    if(0.465 <= dprima && dprima < 0.75){
                                        energy += eij*(80-(64.5*dprima));
                                        //                                        collisionCounter++;
                                        //                                        System.out.println("2 slot: "+(eij*(80-(64.5*dprima))));
                                    }
                                    else{
                                        if(0.75 <= dprima && dprima < 0.8929){
                                            energy += ( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) );
                                            //                                            System.out.println("3 slot: "+( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                        }
                                        else{
                                            if(0.8929 <= dprima && dprima < 2.3){
                                                energy += ( 0.99*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) );
                                                //                                                System.out.println("4 slot: "+( 0.99*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                            }
                                        }
                                    }
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        return ((collisionCounter/possibleCollision)*29)+energy;
        //        return energy;
    }
    
    public static double energySCBBOPUS(AminoAcid aa1, AminoAcid aa2){
        double energy=0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1,aminoAcidIndex2 = -1;;
        String[] atomList1,atomList2;
        double distance, MIN_DISTANCE, krep = 5.882, katt = 0.08;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa1.getPDBName());
        atomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa2.getPDBName());
        atomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        double eij,dprima,lambda;
        
        for (int i = 0; i < atomList1.length; i++) {
            if (aa1 != null && aa1.hasAtom(atomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < atomList2.length; j++) {
                    if (aa2 != null && aa2.hasAtom(atomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(atomList1[i]) && !StructureUtil.isSideChainAtom(atomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = aa1.getAtom(atomList1[i]);
                                atom2 = aa2.getAtom(atomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                eij=wellDepths.get(atom1.getName().substring(0, 1) +"-"+atom2.getName().substring(0,1));
                                lambda=1.6;
                                
                                MIN_DISTANCE = StructureUtil.radius(aa1, atom1) + StructureUtil.radius(aa2, atom2);
                                dprima=distance/MIN_DISTANCE;
                                possibleCollision++;
                                if(dprima > 0 && dprima<(1/1.33)){
                                    energy += lambda*(49.69 - (40.06*dprima));
                                    //                                    System.out.println("1 slot: "+(50*eij));
                                    collisionCounter++;
                                }
                                else{
                                    if((1/1.33) < dprima && dprima <= (1/1.12)){
                                        energy += ( lambda*eij*(Math.pow(dprima,-12) - 2*(Math.pow(dprima,-6))) );
                                        //                                        collisionCounter++;
                                        //                                        System.out.println("2 slot: "+(eij*(80-(64.5*dprima))));
                                    }
                                    else{
                                        if((1/1.12) < dprima && dprima < 2.5){
                                            energy += ( eij*(Math.pow(dprima,-12) - 2*(Math.pow(dprima,-6))) );
                                            //                                            System.out.println("3 slot: "+( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                        }
                                    }
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        //        return ((collisionCounter/possibleCollision)*29)+energy;
        return energy;
    }
    
    public static double energySCBBSCWRL4(AminoAcid aa1, AminoAcid aa2){
        double energy=0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1,aminoAcidIndex2 = -1;;
        String[] atomList1,atomList2;
        double distance, MIN_DISTANCE, krep = 5.882, katt = 0.08;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa1.getPDBName());
        atomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, aa2.getPDBName());
        atomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        double eij,dprima;
        
        for (int i = 0; i < atomList1.length; i++) {
            if (aa1 != null && aa1.hasAtom(atomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < atomList2.length; j++) {
                    if (aa2 != null && aa2.hasAtom(atomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(atomList1[i]) && !StructureUtil.isSideChainAtom(atomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = aa1.getAtom(atomList1[i]);
                                atom2 = aa2.getAtom(atomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                eij=wellDepths.get(atom1.getName().substring(0, 1) +"-"+atom2.getName().substring(0,1));
                                
                                MIN_DISTANCE = StructureUtil.radius(aa1, atom1) + StructureUtil.radius(aa2, atom2);
                                dprima=distance/MIN_DISTANCE;
                                possibleCollision++;
                                if(dprima<=0.8254){
                                    energy += 10;
                                    //                                    System.out.println("1 slot: "+(50*eij));
                                    collisionCounter++;
                                }
                                else{
                                    if(0.8254 <= dprima && dprima <= 1){
                                        energy += (57.273*(1-dprima));
                                        //                                        collisionCounter++;
                                        //                                        System.out.println("2 slot: "+(eij*(80-(64.5*dprima))));
                                    }
                                    else{
                                        if(1 < dprima && dprima < (10/9)){
                                            energy += ( eij*Math.pow((10-(9*dprima)), 57.273/(9*eij)) ) - eij;
                                            //                                            System.out.println("3 slot: "+( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                        }
                                        else{
                                            if(10/9 <= dprima && dprima < 4/3){
                                                energy += ( (eij/4)*(Math.pow((9*dprima)-10,2) ) - eij);
                                                //                                                System.out.println("4 slot: "+( 0.99*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                            }
                                        }
                                    }
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        return ((collisionCounter/possibleCollision)*29)+energy;
        //        return energy;
    }
    //</editor-fold>
    
    public static double totalEnergySCBB(int i, int rot){
        return allSCBBInteractions.get(i).get(rot);
    }

    //<editor-fold defaultstate="collapsed" desc="Calcular energía SC-SC">
    public static double calculateEnergyBetweenSC(AminoAcid a1, AminoAcid a2) {
        double temperatureSumCol = 0.0, temperatureSum = 0.0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1, aminoAcidIndex2 = -1;
        String[] sideChainAtomList1, sideChainAtomList2;
        double distance, MIN_DISTANCE, krep = 5.882, katt = 0.08;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a1.getPDBName());
        sideChainAtomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a2.getPDBName());
        sideChainAtomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        
        for (int i = 0; i < sideChainAtomList1.length; i++) {
            if (a1 != null && a1.hasAtom(sideChainAtomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < sideChainAtomList2.length; j++) {
                    if (a2 != null && a2.hasAtom(sideChainAtomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && StructureUtil.isSideChainAtom(sideChainAtomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = a1.getAtom(sideChainAtomList1[i]);
                                atom2 = a2.getAtom(sideChainAtomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                
                                MIN_DISTANCE = StructureUtil.radius(a1, atom1) + StructureUtil.radius(a2, atom2);
                                possibleCollision++;
                                //                                if(distance <=(MIN_DISTANCE*0.6))
                                //                                    collisionCounter++;
                                if (distance <= MIN_DISTANCE) {
                                    temperatureSumCol += krep * (1 - (distance / MIN_DISTANCE));
                                    collisionCounter++;
                                } else if ((distance > MIN_DISTANCE) && (distance < (2 * MIN_DISTANCE))) {
                                    temperatureSum += katt * (Math.pow(distance / MIN_DISTANCE, 2) - 3 * (distance / MIN_DISTANCE) + 2);
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        if((temperatureSumCol + temperatureSum)!=0){
            totalvdw += (temperatureSumCol + temperatureSum);
            totalcratio += (collisionCounter/possibleCollision)*19.4861137;
            c++;
        }
        //         return (collisionCounter/possibleCollision);
        return ((collisionCounter/possibleCollision)*19.4861137)+(temperatureSumCol + temperatureSum); //102
//                return (temperatureSumCol + temperatureSum);
    }
    
    public static double calculateEnergyBetweenSCRASP(AminoAcid a1, AminoAcid a2) {
        double temperatureSumCol = 0.0, temperatureSum = 0.0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1, aminoAcidIndex2 = -1;
        String[] sideChainAtomList1, sideChainAtomList2;
        double distance, MIN_DISTANCE;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a1.getPDBName());
        sideChainAtomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a2.getPDBName());
        sideChainAtomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        double eij,dprima;
        
        for (int i = 0; i < sideChainAtomList1.length; i++) {
            if (a1 != null && a1.hasAtom(sideChainAtomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < sideChainAtomList2.length; j++) {
                    if (a2 != null && a2.hasAtom(sideChainAtomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && StructureUtil.isSideChainAtom(sideChainAtomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = a1.getAtom(sideChainAtomList1[i]);
                                atom2 = a2.getAtom(sideChainAtomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                eij=StructureUtil.wellDepths.get(atom1.getName().substring(0, 1) +"-"+atom2.getName().substring(0,1));
                                
                                MIN_DISTANCE = StructureUtil.radius(a1, atom1) + StructureUtil.radius(a2, atom2);
                                dprima=distance/MIN_DISTANCE;
                                
                                possibleCollision++;
                                if(dprima<0.465){
                                    temperatureSumCol += (50*eij);
                                    //                                    System.out.println("1 slot: "+(50*eij));
                                    collisionCounter++;
                                }
                                else{
                                    if(0.465 <= dprima && dprima < 0.75){
                                        temperatureSumCol += eij*(80-(64.5*dprima));
                                                                                collisionCounter++;
                                        //                                        System.out.println("2 slot: "+(eij*(80-(64.5*dprima))));
                                    }
                                    else{
                                        if(0.75 <= dprima && dprima < 0.8929){
//                                            collisionCounter++;
                                            temperatureSum += ( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) );
                                            //                                            System.out.println("3 slot: "+( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                        }
                                        else{
                                            if(0.8929 <= dprima && dprima < 2.3){
                                                temperatureSum += ( 0.99*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) );
                                                //                                                System.out.println("4 slot: "+( 0.99*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                            }
                                        }
                                    }
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        totalvdw += (temperatureSumCol + temperatureSum);
        totalcratio += (Double)(collisionCounter/possibleCollision)*150;
        if(Double.isNaN(collisionCounter/possibleCollision)) {
            System.out.println(collisionCounter+"/"+possibleCollision+" = "+collisionCounter/possibleCollision);
        }
        c++;
//                 return (collisionCounter/possibleCollision);
//        return ((collisionCounter/possibleCollision)*150)+(temperatureSumCol + temperatureSum);
                return (temperatureSumCol + temperatureSum);
    }
    
    public static double calculateEnergyBetweenSCOPUS(AminoAcid a1, AminoAcid a2) {
        double temperatureSumCol = 0.0, temperatureSum = 0.0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1, aminoAcidIndex2 = -1;
        String[] sideChainAtomList1, sideChainAtomList2;
        double distance, MIN_DISTANCE;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a1.getPDBName());
        sideChainAtomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a2.getPDBName());
        sideChainAtomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        double eij,dprima,lambda;
        String query="";
        
        for (int i = 0; i < sideChainAtomList1.length; i++) {
            if (a1 != null && a1.hasAtom(sideChainAtomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < sideChainAtomList2.length; j++) {
                    if (a2 != null && a2.hasAtom(sideChainAtomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && StructureUtil.isSideChainAtom(sideChainAtomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = a1.getAtom(sideChainAtomList1[i]);
                                atom2 = a2.getAtom(sideChainAtomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                query=atom1.getName().substring(0, 1) +"-"+atom2.getName().substring(0,1);
                                eij=StructureUtil.wellDepths.get(query);
                                
                                MIN_DISTANCE = StructureUtil.radius(a1, atom1) + StructureUtil.radius(a2, atom2);
                                dprima=distance/MIN_DISTANCE;
                                lambda=1.6;
                                if(query.equalsIgnoreCase("C-C")){
                                    if((a1.getPDBName().equalsIgnoreCase("HIS") || a1.getPDBName().equalsIgnoreCase("PHE") || a1.getPDBName().equalsIgnoreCase("TRP") || a1.getPDBName().equalsIgnoreCase("TYR")) && (a2.getPDBName().equalsIgnoreCase("HIS") || a2.getPDBName().equalsIgnoreCase("PHE") || a2.getPDBName().equalsIgnoreCase("TRP") || a2.getPDBName().equalsIgnoreCase("TYR")) ){
                                        lambda=1;
                                    }
                                }
                                
                                possibleCollision++;
                                if(dprima > 0 && dprima<(1/1.33)){
                                    temperatureSumCol += lambda*(49.69 - (40.06*dprima));
                                    //                                    System.out.println("1 slot: "+(50*eij));
                                    collisionCounter++;
                                }
                                else{
                                    if((1/1.33) < dprima && dprima <= (1/1.12)){
                                        temperatureSumCol += ( lambda*eij*(Math.pow(dprima,-12) - 2*(Math.pow(dprima,-6))) );
                                        //                                        collisionCounter++;
                                        //                                        System.out.println("2 slot: "+(eij*(80-(64.5*dprima))));
                                    }
                                    else{
                                        if((1/1.12) < dprima && dprima < 2.5){
                                            temperatureSum += ( eij*(Math.pow(dprima,-12) - 2*(Math.pow(dprima,-6))) );
                                            //                                            System.out.println("3 slot: "+( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                        }
                                    }
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        //         return (collisionCounter/possibleCollision);
        //        return ((collisionCounter/possibleCollision)*29)+(temperatureSumCol + temperatureSum);
        return (temperatureSumCol + temperatureSum);
    }
    
    public static double calculateEnergyBetweenSCSCWRL4(AminoAcid a1, AminoAcid a2) {
        double energy = 0.0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1, aminoAcidIndex2 = -1;
        String[] sideChainAtomList1, sideChainAtomList2;
        double distance, MIN_DISTANCE;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a1.getPDBName());
        sideChainAtomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a2.getPDBName());
        sideChainAtomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        double eij,dprima;
        
        for (int i = 0; i < sideChainAtomList1.length; i++) {
            if (a1 != null && a1.hasAtom(sideChainAtomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < sideChainAtomList2.length; j++) {
                    if (a2 != null && a2.hasAtom(sideChainAtomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && StructureUtil.isSideChainAtom(sideChainAtomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = a1.getAtom(sideChainAtomList1[i]);
                                atom2 = a2.getAtom(sideChainAtomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                eij=StructureUtil.wellDepths.get(atom1.getName().substring(0, 1) +"-"+atom2.getName().substring(0,1));
                                
                                MIN_DISTANCE = StructureUtil.radius(a1, atom1) + StructureUtil.radius(a2, atom2);
                                dprima=distance/MIN_DISTANCE;
                                
                                possibleCollision++;
                                if(dprima<=0.8254){
                                    energy += 10;
                                    //                                    System.out.println("1 slot: "+(50*eij));
                                    collisionCounter++;
                                }
                                else{
                                    if(0.8254 <= dprima && dprima <= 1){
                                        energy += (57.273*(1-dprima));
                                        //                                        collisionCounter++;
                                        //                                        System.out.println("2 slot: "+(eij*(80-(64.5*dprima))));
                                    }
                                    else{
                                        if(1 < dprima && dprima < (10/9)){
                                            energy += ( eij*Math.pow((10-(9*dprima)), 57.273/(9*eij)) ) - eij;
                                            //                                            System.out.println("3 slot: "+( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                        }
                                        else{
                                            if(10/9 <= dprima && dprima < 4/3){
                                                energy += ( (eij/4)*(Math.pow((9*dprima)-10,2) ) - eij);
                                                //                                                System.out.println("4 slot: "+( 0.99*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                            }
//                                            else{
//                                                if(dprima >=4/3){
//                                                    temperatureSum += 0.00001;
//                                                }
//                                            }
                                        }
                                    }
                                }
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        if(energy!=0){
            totalvdw += energy;
            totalcratio += (collisionCounter/possibleCollision)*323.804831279;
            c++;
        }
        //         return (collisionCounter/possibleCollision);
        return ((collisionCounter/possibleCollision)*323.804831279)+energy;
        //        return (temperatureSumCol + temperatureSum);
    }
    public static double detailedEnergyBetweenSCSCWRL4(AminoAcid a1, AminoAcid a2) {
        double energy = 0.0;
        
        double collisionCounter = 0, possibleCollision = 0.001;
        int aminoAcidIndex1 = -1, aminoAcidIndex2 = -1;
        String[] sideChainAtomList1, sideChainAtomList2;
        double distance, MIN_DISTANCE;
        Atom atom1, atom2;
        aminoAcidIndex1 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a1.getPDBName());
        sideChainAtomList1 = ListUtil.ATOM_LIST[aminoAcidIndex1];
        aminoAcidIndex2 = Arrays.binarySearch(ListUtil.THREE_LETTER_CODE, a2.getPDBName());
        sideChainAtomList2 = ListUtil.ATOM_LIST[aminoAcidIndex2];
        double eij,dprima;
        double E=0;
        
        for (int i = 0; i < sideChainAtomList1.length; i++) {
            if (a1 != null && a1.hasAtom(sideChainAtomList1[i])) {    // && !isSideChainAtom(sideChainAtomList1[i]))
                for (int j = 0; j < sideChainAtomList2.length; j++) {
                    if (a2 != null && a2.hasAtom(sideChainAtomList2[j])) {  // && !isSideChainAtom(sideChainAtomList2[j]))
                        if (StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && StructureUtil.isSideChainAtom(sideChainAtomList2[j])){//!(!StructureUtil.isSideChainAtom(sideChainAtomList1[i]) && !StructureUtil.isSideChainAtom(sideChainAtomList2[j]))) {
                            try {
                                atom1 = a1.getAtom(sideChainAtomList1[i]);
                                atom2 = a2.getAtom(sideChainAtomList2[j]);
                                distance = Calc.getDistance(atom1, atom2);
                                eij=StructureUtil.wellDepths.get(atom1.getName().substring(0, 1) +"-"+atom2.getName().substring(0,1));
                                
                                MIN_DISTANCE = StructureUtil.radius(a1, atom1) + StructureUtil.radius(a2, atom2);
                                dprima=distance/MIN_DISTANCE;
                                
                                possibleCollision++;
                                if(dprima<=0.8254){
                                    E = 10;
                                    energy += E;
                                    //                                    System.out.println("1 slot: "+(50*eij));
                                    collisionCounter++;
                                }
                                else{
                                    if(0.8254 <= dprima && dprima <= 1){
                                        E = (57.273*(1-dprima));
                                        energy += E;
                                        if((57.273*(1-dprima))>10){
                                            System.out.println("Mayor que 30 en 2 con: "+dprima);
                                        }
                                        //                                        collisionCounter++;
                                        //                                        System.out.println("2 slot: "+(eij*(80-(64.5*dprima))));
                                    }
                                    else{
                                        if(1 < dprima && dprima < (10/9)){
                                            E = ( eij*Math.pow((10-(9*dprima)), 57.273/(9*eij)) ) - eij;
                                            energy += E;
                                            if((( eij*Math.pow((10-(9*dprima)), 57.273/(9*eij)) ) - eij)>10){
                                                System.out.println("Mayor que 30 en 3 con: "+dprima);
                                            }
                                            //                                            System.out.println("3 slot: "+( 1.63*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                        }
                                        else{
                                            if(10/9 <= dprima && dprima < 4/3){
                                                E = ( (eij/4)*(Math.pow((9*dprima)-10,2) ) - eij);
                                                energy += E;
                                                if((eij/4)*(Math.pow((9*dprima)-10,2) ) - eij>10){
                                                    System.out.println("Mayor que 30 en 4 con: "+dprima);
                                                }
                                                //                                                System.out.println("4 slot: "+( 0.99*eij*(Math.pow(1/dprima,12) - 2*(Math.pow(1/dprima,6))) ));
                                            }
//                                            else{
//                                                if(dprima >=4/3){
//                                                    temperatureSum += 0.00001;
//                                                }
//                                            }
                                        }
                                    }
                                }
                                System.out.println("Energía entre "+atom1.getName()+" - "+atom2.getName()+ ": "+E+" acumulado: "+energy);
                                E=0;
                            } catch (StructureException ex) {
                                Logger.getLogger(StructureUtil.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        }
        System.out.println("Total de energía: "+energy);
        if(energy!=0){
            totalvdw += energy;
            totalcratio += (collisionCounter/possibleCollision)*323.804831279;
            c++;
        }
        //         return (collisionCounter/possibleCollision);
        return ((collisionCounter/possibleCollision)*323.804831279)+energy;
        //        return (temperatureSumCol + temperatureSum);
    }
    //</editor-fold>
    
    
    public static double getInteraction(int i, int r, int j, int s) {
        HashMap<Integer, HashMap<Integer, Double>> A;
        HashMap<Integer, Double> B;
        double C = 0;
        int temp=0;
        if(j<i){
            temp=i;i=j;j=temp;
            temp=r;r=s;s=temp;
        }
        
        if(allInteractions.get(i)==null)
            return 0;
        
        A = allInteractions.get(i).get(r);
        if (A == null) {
//            System.out.println("return 0; rotamer " + r + " of " + i + " not found");
            return 0;
        } else {
            B = A.get(j);
            if (B == null) {
//                System.out.println("return 0; interaction between " + i + " and " + j + " not found");
                return 0;
            } else {
                C = B.get(s) == null ? Double.NaN : B.get(s);
                if (Double.isNaN(C)) {
//                    System.out.println("return 0; interaction between " + r + " of " + i + " and " + s + " of " + j + " not found.");
                    return 0;
                }
                return C;
            }

        }
//        return allInteractions.get(i).get(r).get(j).get(s);
    }
    
    public double getTotalEnergyUnefficient(){
        double energy=0;
        AminoAcid a1,a2;
        
        for(int i=1;i<aGrid.aminoacidMap.size();i++){
            for(int j=i+1;j<aGrid.aminoacidMap.size();j++){
                a1=aGrid.aminoacidMap.get(i).getAminoacid();
                a2=aGrid.aminoacidMap.get(j).getAminoacid();
                if(!a1.getPDBName().equalsIgnoreCase("ALA") && !a1.getPDBName().equalsIgnoreCase("GLY") && !a2.getPDBName().equalsIgnoreCase("ALA") && !a2.getPDBName().equalsIgnoreCase("GLY"))
                    energy+= calculateEnergyBetweenSC(aGrid.getAminoacid(i),aGrid.getAminoacid(j));
            }
        }
        AllRotamerInteractions.Energy = energy;
        return energy;
    }
    
    public static double getTotalEnergyUnefficient(Solution sol){
        double energy=0;
        int r,s1;
        
        for(int i=0;i<aGrid.aminoacidMap.size()-1;i++){
            r=Integer.parseInt(sol.getRomaterVector().get(0).get(i));
            for(int j=i+1;j<aGrid.aminoacidMap.size();j++){
                s1=Integer.parseInt(sol.getRomaterVector().get(0).get(j));
                energy += getInteraction(i,r,j,s1);
            }
        }
        AllRotamerInteractions.Energy=energy;
        return energy;
    }
    
    public static double getTotalEnergyEfficient(Solution sol){
        double energy=0;
        int r,s1;
        ArrayList<Integer> aas2verify;
        int key1,key2;
        Object[] keys=aGrid.aminoacidMap.keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        double e=0;
        for(int i=0;i<keys.length;i++){
            key1=Integer.parseInt(keys[i].toString())-1;
            r=Integer.parseInt(sol.getRomaterVector().get(0).get(key1));
            aas2verify=AAsToVerify.get(key1);
            
            for(int j:aas2verify){
                if(i<j){
                    s1=Integer.parseInt(sol.getRomaterVector().get(0).get(j));
                    e += getInteraction(i,r,j,s1);
//                    System.out.println("Energy en i="+i+" y j="+j+" es: "+energy);
                }
            }
//            System.out.println(key1+".- "+e);
            energy +=e;
            e=0;
        }
        AllRotamerInteractions.Energy=energy;
        return energy;
    }
    
    public static double getTotalEnergyEfficient(){
        double energy=0;
        int r,s1;
        ArrayList<Integer> aas2verify;
        int key1;
        Object[] keys=aGrid.aminoacidMap.keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        for(int i=0;i<keys.length;i++){
            key1=Integer.parseInt(keys[i].toString())-1;
            r=Rotamers.get(key1);
            aas2verify=AAsToVerify.get(key1);
            
            for(int j:aas2verify){
                if(i<j){
                    s1=Rotamers.get(j);
                    energy += getInteraction(i,r,j,s1);
//                    System.out.println("Energy en i="+i+" y j="+j+" es: "+energy);
                }
            }
            
        }
        AllRotamerInteractions.Energy=energy;
        return energy;
    }
    
    public static double getTotalEnergyEfficientDetailed(){
        double energy=0,E=0;
        int r,s1;
        ArrayList<Integer> aas2verify;
        int key1;
        Object[] keys=aGrid.aminoacidMap.keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        for(int i=0;i<keys.length;i++){
            key1=Integer.parseInt(keys[i].toString())-1;
            r=Rotamers.get(key1);
            aas2verify=AAsToVerify.get(key1);
            
            for(int j:aas2verify){
                if(i<j){
                    s1=Rotamers.get(j);
                    E = getInteraction(i,r,j,s1);
                    energy += E;
                    if(E!=0)
                        System.out.println("Energy en i="+i+" y j="+j+" es: "+E);
                }
            }
            
        }
        System.out.println("Total: "+energy);
        AllRotamerInteractions.Energy=energy;
        return energy;
    }
    
    public static double getAminoacidInteractions(int i){
        double interactionEnergy=0;
        ArrayList<Integer> nearAAs= AAsToVerify.get(i);
        int r= Rotamers.get(i),s1=0;
        String cad="";
        
        if(nearAAs!=null) {
            for(int j:nearAAs){
                if(true){
                s1=Rotamers.get(j);
                interactionEnergy += getInteraction(i,r,j,s1);
//                if(i==33/*getInteraction(i,r,j,s1)!=0*/)
//                    System.out.println("interacción de "+i+":"+r+" con "+j+":"+s1+" = "+getInteraction(i,r,j,s1));
                }
            }
        }
        
        return interactionEnergy;
    }
    
    public final HashMap<Integer,Integer> initRotamers(Solution sol){
        HashMap<Integer,Integer> rots=new HashMap<>();
        Object[] keys=sol.getRomaterVector().get(0).keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        int aa=0;
        for(int i=0;i<sol.getRomaterVector().get(0).size();i++){
            aa=Integer.parseInt(keys[i].toString());
            rots.put(aa, Integer.parseInt(sol.getRomaterVector().get(0).get(aa)));
        }
        return rots;
    }
    
    public final HashMap<Integer,Double> initAAInteractions(){
        HashMap<Integer,Double> aaInteractions=new HashMap<>();
        AminoAcid a;
        int key=0;
        Object[] keys=aGrid.aminoacidMap.keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        for(int i=0;i<keys.length;i++){
            key=Integer.parseInt(keys[i].toString())-1;
            a=aGrid.getAminoacid(key);
            if(!a.getPDBName().equalsIgnoreCase("ALA") && !a.getPDBName().equalsIgnoreCase("GLY")){
                aaInteractions.put(key, getAminoacidInteractions(key));
//                System.out.println("Inter en "+key+": "+aaInteractions.get(key));
            }else{
                aaInteractions.put(key, 0.0);
            }
        }
        return aaInteractions;
    }
    
    public static Solution setMaxProbEnabled(Solution sol){
        RotamerLibrary rl;
        double prob=0;
        
        Object[] keys=sol.getRomaterVector().get(0).keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        int i=0;
        for (int group = 0; group < keys.length; group++) {
            i=Integer.parseInt(keys[group].toString());
            rl=rlc.getRotamerLibrary(aGrid.getAminoacid(i).getPDBName());
            if(aGrid.getAminoacid(i).getPDBName().equalsIgnoreCase("ALA") || aGrid.getAminoacid(i).getPDBName().equalsIgnoreCase("GLY"))
                continue;
            for(int rot:enabledRotamers.get(i)){
                if(rl.getRotamer().get(rot).getProbabilityValue()>prob){
                    prob=rl.getRotamer().get(rot).getProbabilityValue();
                    sol.getRomaterVector().get(0).put(i, rot+"");
                }
            }
            prob=0;

        }
        
        return sol;
    }
    
    public static Solution setBestSCBBRots(Solution sol){
        AminoAcid aa;
        RotamerLibrary rl;
        double bestEnergy;
        int bestRot=-1;
        
        Object[] keys=sol.getRomaterVector().get(0).keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        int i=0;
        
        for(int key=0; key<keys.length;key++){
            i=Integer.parseInt(keys[key].toString());
            aa=aGrid.getAminoacid(i);
            if(aa.getPDBName().equalsIgnoreCase("ALA") || aa.getPDBName().equalsIgnoreCase("GLY"))
                continue;
            rl=rlc.getRotamerLibrary(aa.getPDBName());
            bestEnergy=Double.MAX_VALUE;
            for(int r=0;r < rl.getRotamer().size(); r++){
                if(rl.getRotamer().get(r).getProbabilityValue() < 1)
                    continue;
                if(totalEnergySCBB(i,r) < bestEnergy){
                    bestEnergy=totalEnergySCBB(i,r);
                    bestRot=r;
                }
            }
            sol.getRomaterVector().get(0).put(i, bestRot+"");
            bestRot=-1;
        }
        
        return sol;
    }
    
    public static Solution setBestSCBBProbRots(Solution sol){
        AminoAcid aa;
        RotamerLibrary rl;
        double bestEnergy,bestProb;
        int bestRot=-1,bestRot2=-1;
        
        Object[] keys=sol.getRomaterVector().get(0).keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        int i=0;
        
        for(int key=0; key<keys.length;key++){
            i=Integer.parseInt(keys[key].toString());
            aa=aGrid.getAminoacid(i);
            if(aa.getPDBName().equalsIgnoreCase("ALA") || aa.getPDBName().equalsIgnoreCase("GLY"))
                continue;
            rl=rlc.getRotamerLibrary(aa.getPDBName());
            bestEnergy=Double.MAX_VALUE;
            bestProb=0;
            for(int r=0;r < rl.getRotamer().size(); r++){
                if(rl.getRotamer().get(r).getProbabilityValue() < 1)
                    continue;
                if(totalEnergySCBB(i,r) < bestEnergy){
                    bestEnergy=totalEnergySCBB(i,r);
                    bestRot=r;
                }
                if(rl.getRotamer().get(r).getProbabilityValue() > bestProb){
                    bestProb=rl.getRotamer().get(r).getProbabilityValue();
                    bestRot2=r;
                }
            }
            Rotamers.put(i,bestRot);
            bestEnergy=getAminoacidInteractions(i);
            Rotamers.put(i,bestRot2);
            bestEnergy=getAminoacidInteractions(i);
            if(bestEnergy>bestProb)
                sol.getRomaterVector().get(0).put(i, bestRot+"");
            else
                sol.getRomaterVector().get(0).put(i, bestRot2+"");
            bestRot=-1;
        }
        
        return sol;
    }
    
    public void DEE(){
        int nResidues = TabuSearch.getSeqResLength(s);
        RotamerLibrary rl;
        ArrayList<Integer> enabled,disabled,nearAAs;
        double energyDifference;
        int total=0, count=0,bigtotal=0;
        Object[] keys=sol.getRomaterVector().get(0).keySet().toArray(new Integer[0]);
        Arrays.sort(keys);
        for(int i=0; i<nResidues; i++){
            int aa=Integer.parseInt(keys[i].toString());
            String pdbName=aGrid.getAminoacid(aa).getPDBName();
            if(pdbName.equalsIgnoreCase("ALA") || pdbName.equalsIgnoreCase("GLY"))
                continue;
            rl=rlc.getRotamerLibrary(pdbName);
            enabled=new ArrayList<>();
            disabled=new ArrayList<>();
            nearAAs= AAsToVerify.get(aa);
            
            for(int g=0; g<rl.getRotamer().size(); g++){
                bigtotal++;
                if(rl.getRotamer().get(g).getProbabilityValue() < 1) {
                    continue;
                }
                total++;
                
                for(int h=0; h<rl.getRotamer().size(); h++){
                    if(rl.getRotamer().get(h).getProbabilityValue() < 1) {
                        continue;
                    }
                    
                    energyDifference=0;
                    for(int j:nearAAs){
                        if(aGrid.getAminoacid(j).getPDBName().equalsIgnoreCase("ALA") || aGrid.getAminoacid(j).getPDBName().equalsIgnoreCase("GLY"))
                            continue;
                        energyDifference+=minGminusH(aa,g,h,j);
                    }
//                    System.out.println("Energy Diference: ("+totalEnergySCBB(i,g)+" - "+totalEnergySCBB(i,h)+") + "+energyDifference+" = "+((totalEnergySCBB(i,g) - totalEnergySCBB(i,h)) + energyDifference));
//                    energyDifference = (totalEnergySCBB(i,g) - totalEnergySCBB(i,h))+ (aGrid.getRotamerFrequencyRASP(pdbName, g) - aGrid.getRotamerFrequencyRASP(pdbName, h)) + energyDifference;
                    energyDifference = (totalEnergySCBB(aa,g) - totalEnergySCBB(aa,h))+ energyDifference;
                    if(energyDifference > 0.5){
//                        System.out.println("Desactivado!!");
                        count++;
                        disabled.add(g);
                        break;
                    }
                    
                }
                if(disabled.contains(g)){
                    continue;
                }else{
                    enabled.add(g);
                }
            }
            enabledRotamers.put(aa, enabled);
        }
        System.out.println("De "+bigtotal+"/"+total+" se desactivaron: "+count);
        System.out.println("vdw prom: "+(totalvdw/c));
        System.out.println("cratio prom:"+(totalcratio/c)+Double.isNaN(totalcratio));
    }
    
    public final void  initWellDepths(){
        wellDepths.put("C-C",0.150);
        wellDepths.put("C-N",0.155);
        wellDepths.put("C-O",0.173);
        wellDepths.put("C-S",0.173);
        wellDepths.put("C-H",0.055);
        
        wellDepths.put("N-C",0.155);
        wellDepths.put("N-N",0.160);
        wellDepths.put("N-O",0.179);
        wellDepths.put("N-S",0.179);
        wellDepths.put("N-H",0.157);
        
        wellDepths.put("O-C",0.173);
        wellDepths.put("O-N",0.179);
        wellDepths.put("O-O",0.2);
        wellDepths.put("O-S",0.2);
        wellDepths.put("O-H",0.063);
        
        wellDepths.put("S-C",0.173);
        wellDepths.put("S-N",0.179);
        wellDepths.put("S-O",0.2);
        wellDepths.put("S-S",0.2);
        wellDepths.put("S-H",0.063);
        
        wellDepths.put("H-C",0.055);
        wellDepths.put("H-N",0.057);
        wellDepths.put("H-O",0.063);
        wellDepths.put("H-S",0.063);
        wellDepths.put("H-H",0.020);
    }
}
